package com.yumeisoft.aitables;

import cn.hutool.core.io.resource.ResourceUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.yumeisoft.aitables.dialog.DatabaseConfigDialog;
import com.yumeisoft.aitables.entity.*;
import com.yumeisoft.aitables.util.CodeExtractor;
import com.yumeisoft.aitables.util.OllamaClient;
import lombok.Getter;
import lombok.Setter;

import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ProjectBuilder {
    private static final String MODULE_PROMPT_FILE = "模块推理器.txt";
    private static final String ENTITY_PROMPT_FILE = "实体表推理器.txt";
    private static final String LANGUAGE = "json";
    private static final Gson GSON = new Gson();

    private final OllamaClient client = new OllamaClient();
    private final StringBuilder contextBuilder = new StringBuilder();
    private final ProjectEntity projectEntity = new ProjectEntity();
    @Setter @Getter
    private DatabaseConfigVO config;

    public static void main(String[] args) {
        DatabaseConfigDialog dialog = new DatabaseConfigDialog();
        dialog.showDialog((result)->{
            ProjectBuilder builder = new ProjectBuilder();
            builder.setConfig(result);
            try {
                builder.buildProject();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
            return true;
        });
    }

    public void buildProject() throws SQLException {
//        client.setModel("deepseek-r1:32b");
//        client.setModel("deepseek-r1:7b");
        client.setModel(ResourceUtil.readStr("Model.txt", Charset.defaultCharset()));

        // 初始化上下文
        appendContext("用户的原始需求是:\n%s\n", config.getPrompt());
        projectEntity.setDemand(config.getPrompt());


        // 推理核心模块
        LlmAnswerPack moduleAnswer = queryModules(config.getPrompt());
        List<String> modules = parseModules(moduleAnswer);
        modules.forEach(item -> projectEntity.getModules().add(new ModuleEntity(item)));

        // 推理实体表
        processEntities(modules);

        // 推理字段
        processColumns();

        System.out.println(getContext());
        System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(projectEntity));
    }

    public static Connection getConnection(DatabaseConfigVO config) throws SQLException {
        // 检查必填字段是否为空
        if (config == null) {
            throw new IllegalArgumentException("DatabaseConfigVO 不能为空");
        }
        if (config.getMysqlHost() == null || config.getMysqlHost().isEmpty()) {
            throw new IllegalArgumentException("mysqlHost 不能为空");
        }
        if (config.getDatabaseName() == null || config.getDatabaseName().isEmpty()) {
            throw new IllegalArgumentException("databaseName 不能为空");
        }

        // 构建 JDBC URL
        String jdbcUrl = "jdbc:mysql://" + config.getMysqlHost() + ":" + config.getPort()
                + "/" + config.getDatabaseName();

        // 设置 MySQL 连接属性（可选）
        java.util.Properties props = new java.util.Properties();
        props.setProperty("user", config.getUsername());
        props.setProperty("password", config.getPassword());

        // 获取数据库连接
        return DriverManager.getConnection(jdbcUrl, props);
    }


    private LlmAnswerPack queryModules(String question) {
        return queryLlm(
                MODULE_PROMPT_FILE,
                question,
                List.of("已知要设计的模块有:${answer}\n")
        );
    }

    private List<String> parseModules(LlmAnswerPack answerPack) {
        return GSON.fromJson(
                answerPack.getAnswerList().get(0),
                new TypeToken<List<String>>() {
                }.getType()
        );
    }

    private void processEntities(List<String> modules) {
        appendContext("\n已知已设计的实体表有：\n");

        modules.forEach(module -> {
            LlmAnswerPack entityAnswer = queryLlm(
                    ENTITY_PROMPT_FILE,
                    module,
                    List.of(module + ":${answer}\n")
            );
            List<TableEntity> moduleTablesList = projectEntity.getModules().stream()
                    .filter(item -> item.getName().equals(module))
                    .toList().get(0).getTables();
            StringBuilder contextAppend = new StringBuilder();
            contextAppend.append(module).append(":");
            new Gson().fromJson(entityAnswer.getAnswerList().get(0), List.class)
                    .forEach(item -> {
                        String name = ((Map) item).get("name").toString();
                        String code = ((Map) item).get("code").toString();
                        TableEntity table = new TableEntity(name);
                        table.setCode(code);
                        moduleTablesList.add(table);
                        contextAppend.append(name).append("(").append(code).append("),");
                    });
            contextAppend.deleteCharAt(contextAppend.length() - 1);
            contextAppend.append("\n");
            appendContext(contextAppend.toString());
        });
    }

    private void processColumns() {
        appendContext("\n已知已设计的表结构有：\n");

        projectEntity.getModules().forEach(module -> {
            module.getTables().forEach(table -> {
                String tableName = table.getName();
                String tableCode = table.getCode();
                String question = "请帮我推理[" + module.getName() + "]模块下的[" + tableName + "(" + tableCode + ")]表";

                List<String> description=new ArrayList<>();
                while(description.size()==0){
                    LlmAnswerPack pack = client.queryLlm("表结构推理器.txt", getContext(), question, "sql",
                            List.of("", ":${answer}\n")
                    );
                    description = CodeExtractor.getFromAnswer(pack.getLlmAnswer(), "text");
                    table.setCreateTableSql(pack.getAnswerList().get(0));
                }

                // 自动建表
                try(Connection connection = getConnection(config)){
                    try(PreparedStatement stat = connection.prepareStatement(table.getCreateTableSql());){
                        stat.execute();
                    }catch (Exception e){
                        throw new RuntimeException(e);
                    }
                }catch (Exception e){
                    throw new RuntimeException(e);
                }
                appendContext(description.get(0).trim()+"\n");
            });
        });
    }

    private LlmAnswerPack queryLlm(String promptFile, String question, List<String> format) {
        return client.queryLlm(
                promptFile,
                getContext(),
                question,
                LANGUAGE,
                format
        );
    }

    private void appendContext(String format, Object... args) {
        contextBuilder.append(String.format(format, args));
    }

    private void appendContext(String content) {
        contextBuilder.append(content);
    }

    private String getContext() {
        return contextBuilder.toString();
    }
}